package com.sharer.last.interceptor;


import com.sharer.last.annotation.AccessLimit;
import com.sharer.last.base.model.R;
import com.sharer.last.service.RedisService;
import com.sharer.last.utils.IpAddressUtils;
import com.sharer.last.utils.JacksonUtils;
import org.springframework.stereotype.Component;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.handler.HandlerInterceptorAdapter;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.PrintWriter;

/**
 * 访问控制拦截器
 *
 * @ClassName AccessLimitInterceptor
 * @Author wangjin
 * @Date 2023/5/5 20:56
 * @Description
 * @Version 1.0
 */
@Component
public class AccessLimitInterceptor extends HandlerInterceptorAdapter {
	@Resource
	RedisService redisService;

	@Override
	public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
		if (handler instanceof HandlerMethod) {
			HandlerMethod handlerMethod = (HandlerMethod) handler;
			AccessLimit   accessLimit   = handlerMethod.getMethodAnnotation(AccessLimit.class);
			//方法上没有访问控制的注解，直接通过
			if (accessLimit == null) {
				return true;
			}
			int seconds = accessLimit.seconds();
			int maxCount = accessLimit.maxCount();
			String ip = IpAddressUtils.getIpAddress(request);
			String method = request.getMethod();
			String requestURI = request.getRequestURI();
			String redisKey = ip + ":" + method + ":" + requestURI;
			Object o = redisService.get(redisKey);
			if (o == null) {
				//在规定周期内第一次访问，存入redis
				redisService.incr(redisKey, 1);
				redisService.setExpireTime(redisKey, seconds);
			} else {
				Integer count = Integer.valueOf("" + o);
				if (count >= maxCount) {
					//超出访问限制次数
					response.setContentType("application/json;charset=utf-8");
					PrintWriter out    = response.getWriter();
					R           result = R.fail(403, accessLimit.msg());
					out.write(JacksonUtils.writeValueAsString(result));
					out.flush();
					out.close();
					return false;
				} else {
					//没超出访问限制次数
					redisService.incr(redisKey, 1);
				}
			}
		}
		return true;
	}
}
